﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Gma.UserActivityMonitor;
using Meridian;
using MeridianZ.ViewModel;
using VkApi;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;

namespace MeridianZ.Views
{
    /// <summary>
    /// Interaction logic for MainView.xaml
    /// </summary>
    public partial class MainView : Window
    {
        private readonly MainViewModel viewModel;
        private bool isPlaying;
        private readonly DispatcherTimer playingProgressTimer;
        private bool playFromSearch;
        private readonly Random r;
        private VkAudio currentAudio;

        public MainView()
        {
            InitializeComponent();

            this.Width = App.Settings.Width;
            this.Height = App.Settings.Height;
            if (App.Settings.Left == -100 || App.Settings.Top == -100)
            {
                this.Left = SystemParameters.PrimaryScreenWidth / 2 - this.Width / 2;
                this.Top = SystemParameters.PrimaryScreenHeight / 2 - this.Height / 2;
            }
            else
            {
                this.Left = App.Settings.Left;
                this.Top = App.Settings.Top;
            }

            viewModel = new MainViewModel();
            this.DataContext = viewModel;

            UsernameTextBlock.MouseLeftButtonDown += (s, e) => viewModel.Login();

            MyAudioList.MouseDoubleClick += (s, e) =>
                                                {
                                                    if (MyAudioList.SelectedIndex != -1)
                                                    {
                                                        playFromSearch = false;
                                                        PlayAudio((VkAudio)MyAudioList.SelectedItem);
                                                    }
                                                };

            SearchList.MouseDoubleClick += (s, e) =>
            {
                if (SearchList.SelectedIndex != -1)
                {
                    playFromSearch = true;
                    PlayAudio((VkAudio)SearchList.SelectedItem);
                }
            };

            MyAudioList.KeyDown += (s, e) =>
            {
                if (e.Key == Key.Enter && MyAudioList.SelectedIndex != -1)
                {
                    playFromSearch = false;
                    PlayAudio((VkAudio)MyAudioList.SelectedItem);
                }
            };

            SearchList.KeyDown += (s, e) =>
            {
                if (e.Key == Key.Enter && SearchList.SelectedIndex != -1)
                {
                    playFromSearch = true;
                    PlayAudio((VkAudio)SearchList.SelectedItem);
                }
            };

            playingProgressTimer = new DispatcherTimer();
            playingProgressTimer.Interval = TimeSpan.FromMilliseconds(100);
            playingProgressTimer.Tick += PlayingProgressTimerTick;

            HookManager.KeyDown += HookManagerKeyDown;
            r = new Random(Environment.TickCount);

            ShuffleButton.IsChecked = App.Settings.Shuffle;
            MediaElement.Volume = App.Settings.Volume;
        }

        private void WindowSourceInitialized(object sender, EventArgs e)
        {
            VolumeSlider.Value = MediaElement.Volume * 100;
            viewModel.Login();
        }

        private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            HookManager.KeyDown -= HookManagerKeyDown;
            App.Settings.Shuffle = ShuffleButton.IsChecked == true;
            App.Settings.Volume = MediaElement.Volume;
        }

        void HookManagerKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (MyAudioList.SelectedIndex == -1 && SearchList.SelectedIndex == -1)
                return;
            switch (e.KeyCode)
            {
                case Keys.MediaPlayPause:
                    PlayPause();
                    break;
                case Keys.MediaNextTrack:
                    NextMedia();
                    break;
                case Keys.MediaPreviousTrack:
                    PrevMedia();
                    break;
                case Keys.MediaStop:
                    MediaElement.Stop();
                    break;
            }
        }

        void PlayingProgressTimerTick(object sender, EventArgs e)
        {
            UpdateProgressSlider();
        }

        void PlayAudio(VkAudio audio)
        {
            if (audio == null)
                return;

            MediaElement.Source = new Uri(audio.Url);
            MediaElement.Play();
            isPlaying = true;
            PlayPauseButton.IsChecked = true;
            PlayingTitle.Text = audio.Artist + " - " + audio.Title;
            playingProgressTimer.Start();

            if (!playFromSearch)
            {
                if (MyAudioList.SelectedIndex == MyAudioList.Items.Count - 1)
                    viewModel.LoadMore(App.Settings.DynamicLoadItemsCount);
            }
            else
            {
                if (SearchList.SelectedIndex == SearchList.Items.Count - 1)
                    viewModel.LoadMore(App.Settings.DynamicLoadItemsCount);
            }

            ThumbPlayButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/pause_thumb.png"));
            this.Title = audio.Title + " - " + audio.Artist;

            FavButton.IsEnabled = true;
            ThumbLikeButton.IsEnabled = true;

            FavButton.IsChecked = audio.IsAddedByUser;

            currentAudio = audio;
        }

        private void PrevButtonClick(object sender, RoutedEventArgs e)
        {
            PrevMedia();
        }

        private void PlayPauseButtonClick(object sender, RoutedEventArgs e)
        {
            PlayPause();
        }

        private void NextButtonClick(object sender, RoutedEventArgs e)
        {
            NextMedia();
        }

        void PlayPause()
        {
            if (MediaElement.Source == null)
            {
                if (!playFromSearch)
                {
                    if (MyAudioList.SelectedIndex == -1 && MyAudioList.Items.Count > 0)
                    {
                        MyAudioList.SelectedIndex = 0;
                        PlayAudio((VkAudio)MyAudioList.SelectedItem);
                    }
                }
                else
                {
                    if (SearchList.SelectedIndex == -1 && SearchList.Items.Count > 0)
                    {
                        SearchList.SelectedIndex = 0;
                        PlayAudio((VkAudio)SearchList.SelectedItem);
                    }
                }
                return;
            }

            if (isPlaying)
            {
                MediaElement.Pause();
                isPlaying = false;
                PlayPauseButton.IsChecked = false;
                ThumbPlayButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/play_thumb.png"));
            }
            else
            {
                MediaElement.Play();
                isPlaying = true;
                PlayPauseButton.IsChecked = true;
                ThumbPlayButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/pause_thumb.png"));
            }
        }

        void PrevMedia()
        {
            if (!playFromSearch)
            {
                if (MyAudioList.Items.Count == 0)
                    return;
                if (ShuffleButton.IsChecked != true)
                {
                    if (MyAudioList.SelectedIndex == -1 || MyAudioList.SelectedIndex == 0)
                        MyAudioList.SelectedIndex = MyAudioList.Items.Count - 1;
                    else
                        MyAudioList.SelectedIndex--;
                }
                else
                {
                    int index = r.Next(0, MyAudioList.Items.Count);
                    MyAudioList.SelectedIndex = index;
                }

                MyAudioList.ScrollIntoView(MyAudioList.SelectedItem);

                PlayAudio((VkAudio)MyAudioList.SelectedItem);
            }
            else
            {
                if (SearchList.Items.Count == 0)
                    return;
                if (ShuffleButton.IsChecked != true)
                {
                    if (SearchList.SelectedIndex == -1 || SearchList.SelectedIndex == 0)
                        SearchList.SelectedIndex = SearchList.Items.Count - 1;
                    else
                        SearchList.SelectedIndex--;
                }
                else
                {
                    int index = r.Next(0, SearchList.Items.Count);
                    SearchList.SelectedIndex = index;
                }

                SearchList.ScrollIntoView(MyAudioList.SelectedItem);

                PlayAudio((VkAudio)SearchList.SelectedItem);
            }
        }

        void NextMedia()
        {
            if (!playFromSearch)
            {
                if (MyAudioList.Items.Count == 0)
                    return;
                if (ShuffleButton.IsChecked != true)
                {
                    if (MyAudioList.SelectedIndex == -1 || MyAudioList.SelectedIndex == MyAudioList.Items.Count - 1)
                        MyAudioList.SelectedIndex = 0;
                    else
                        MyAudioList.SelectedIndex++;
                }
                else
                {
                    int index = r.Next(0, MyAudioList.Items.Count);
                    MyAudioList.SelectedIndex = index;
                }

                MyAudioList.ScrollIntoView(MyAudioList.SelectedItem);

                PlayAudio((VkAudio)MyAudioList.SelectedItem);
            }
            else
            {
                if (SearchList.Items.Count == 0)
                    return;
                if (ShuffleButton.IsChecked != true)
                {
                    if (SearchList.SelectedIndex == -1 || SearchList.SelectedIndex == SearchList.Items.Count - 1)
                        SearchList.SelectedIndex = 0;
                    else
                        SearchList.SelectedIndex++;
                }
                else
                {
                    int index = r.Next(0, SearchList.Items.Count);
                    SearchList.SelectedIndex = index;
                }

                SearchList.ScrollIntoView(SearchList.SelectedItem);

                PlayAudio((VkAudio)SearchList.SelectedItem);
            }
        }

        void UpdateProgressSlider()
        {
            ProgressSlider.ValueChanged -= ProgressSliderValueChanged;
            ProgressSlider.Value = MediaElement.Position.TotalSeconds;
            ProgressSlider.ValueChanged += ProgressSliderValueChanged;

            EstimatedTime.Text = MediaElement.Position.ToString("m\\:ss");
            if (MediaElement.NaturalDuration.HasTimeSpan)
            {
                ProgressSlider.Maximum = MediaElement.NaturalDuration.TimeSpan.TotalSeconds;
                LeftTime.Text = "-" + (MediaElement.Position - MediaElement.NaturalDuration.TimeSpan).ToString("m\\:ss");
                if (MediaElement.NaturalDuration.TimeSpan == MediaElement.Position)
                    NextMedia();
            }

        }

        private void ProgressSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (viewModel.IsLoaded)
            {
                if (MediaElement.IsBuffering)
                    return;
                MediaElement.Position = TimeSpan.FromSeconds(ProgressSlider.Value);
            }
        }

        private void MyAudioListScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var sb = e.OriginalSource as ScrollViewer;
            if (sb == null)
                return;

            if (Math.Abs(e.VerticalOffset + e.ViewportHeight - e.ExtentHeight) < 5)
            {
                viewModel.LoadMore(App.Settings.DynamicLoadItemsCount);
            }
        }

        private void VolumeSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            MediaElement.Volume = VolumeSlider.Value / 100.0f;
        }

        private void SearchBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter && SearchBox.Text.Length > 0)
            {
                Search(SearchBox.Text);
            }

            if (e.Key == Key.Escape)
            {
                SearchBox.Text = string.Empty;
                FocusManager.SetFocusedElement(this, null);
                Keyboard.ClearFocus();
            }
        }

        void Search(string query)
        {
            viewModel.Search(query, App.Settings.DynamicLoadItemsCount);
            SearchIcon.Source = new BitmapImage(new Uri("/Resources/Images/cancel_icon.png", UriKind.Relative));
            if (SearchList.Items.Count == 0)
                ((Storyboard)Resources["FadeInSearchResultsAnim"]).Begin();
        }

        private void SearchListScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var sb = e.OriginalSource as ScrollViewer;
            if (sb == null)
                return;

            if (Math.Abs(e.VerticalOffset + e.ViewportHeight - e.ExtentHeight) < 5)
            {
                viewModel.SearchMore(SearchBox.Text, App.Settings.DynamicLoadItemsCount);
            }
        }

        private void SearchBoxGotFocus(object sender, RoutedEventArgs e)
        {
            if (SearchBox.Text == Properties.Resources.Search)
            {
                SearchBox.Text = "";
                ((Storyboard)Resources["ExpandSearchBoxAnim"]).Begin();
            }
        }

        private void SearchBoxLostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(SearchBox.Text))
            {
                SearchBox.Text = Properties.Resources.Search;
                ((Storyboard)Resources["CollapseSearchBoxAnim"]).Begin();
                ((Storyboard)Resources["FadeOutSearchResultsAnim"]).Begin();
            }
        }


        private void ThumbPrevButtonClick(object sender, EventArgs e)
        {
            PrevMedia();
        }

        private void ThumbPlayButtonClick(object sender, EventArgs e)
        {
            PlayPause();
        }

        private void ThumbNextButtonClick(object sender, EventArgs e)
        {
            NextMedia();
        }

        private void FavButtonClick(object sender, RoutedEventArgs e)
        {
            FavButton.IsChecked = !FavButton.IsChecked;
            LikeDislike();
        }

        void LikeDislike()
        {
            if (FavButton.IsChecked == true)
            {
                viewModel.DeleteAudio(currentAudio);
                FavButton.IsChecked = true;
            }
            else
            {
                viewModel.AddAudio(currentAudio);
                FavButton.IsChecked = false;
            }
            FavButton.IsEnabled = false;
            ThumbLikeButton.IsEnabled = false;
        }

        private void SearchIconMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (SearchList.Items.Count > 0)
            {
                viewModel.SearchResults.Clear();
                SearchIcon.Source = new BitmapImage(new Uri("/Resources/Images/search_icon.png", UriKind.Relative));
                SearchBox.Text = string.Empty;
                FocusManager.SetFocusedElement(this, null);
                Keyboard.ClearFocus();
            }
            else
            {
                if (!string.IsNullOrEmpty(SearchBox.Text))
                    Search(SearchBox.Text);
            }
        }

        private void RemoveItemClick(object sender, RoutedEventArgs e)
        {
            if (MyAudioList.SelectedIndex < 0)
                return;
            viewModel.DeleteAudio((VkAudio)MyAudioList.SelectedItem);
        }

        private void AddItemClick(object sender, RoutedEventArgs e)
        {
            if (SearchList.SelectedIndex < 0)
                return;
            viewModel.AddAudio((VkAudio)SearchList.SelectedItem);
        }

        private void WindowSizeChanged(object sender, SizeChangedEventArgs e)
        {
            App.Settings.Width = this.Width;
            App.Settings.Height = this.Height;
        }

        private void WindowLocationChanged(object sender, EventArgs e)
        {
            App.Settings.Left = this.Left;
            App.Settings.Top = this.Top;
        }

        private void MyAudioListSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (MyAudioList.SelectedIndex != -1)
                SearchList.SelectedIndex = -1;
        }

        private void SearchListSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (SearchList.SelectedIndex != -1)
                MyAudioList.SelectedIndex = -1;
        }

        private void ThumbShuffleButtonClick(object sender, EventArgs e)
        {
            ShuffleButton.IsChecked = !ShuffleButton.IsChecked;
        }

        private void ShuffleButtonChecked(object sender, RoutedEventArgs e)
        {
            ThumbShuffleButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/shuffle_icon_thumb.png"));
        }

        private void ShuffleButtonUnchecked(object sender, RoutedEventArgs e)
        {
            ThumbShuffleButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/shuffle_disabled_icon_thumb.png"));
        }

        private void ThumbLikeButtonClick(object sender, EventArgs e)
        {
            LikeDislike();
            ThumbLikeButton.IsEnabled = false;
        }

        private void FavButtonChecked(object sender, RoutedEventArgs e)
        {
            ThumbLikeButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/notfav_icon_thumb.png"));
        }

        private void FavButtonUnchecked(object sender, RoutedEventArgs e)
        {
            ThumbLikeButton.ImageSource = new BitmapImage(new Uri("pack://application:,,,/MeridianZ;component/Resources/Images/fav_icon_thumb.png"));
        }
    }
}
